/**
 * PPH系统管理界面JavaScript
 * 兼容 IE11+ 和现代浏览器
 */

// 浏览器兼容性检查和polyfill
(function() {
    'use strict';

    // 检测浏览器类型和版本
    var userAgent = navigator.userAgent;
    var isIE = userAgent.indexOf('MSIE') !== -1 || userAgent.indexOf('Trident/') !== -1;
    var isEdge = userAgent.indexOf('Edge/') !== -1;
    var isChrome = userAgent.indexOf('Chrome/') !== -1 && userAgent.indexOf('Edge/') === -1;
    var isFirefox = userAgent.indexOf('Firefox/') !== -1;
    var isSafari = userAgent.indexOf('Safari/') !== -1 && userAgent.indexOf('Chrome/') === -1;

    // 添加浏览器类名到body
    document.addEventListener('DOMContentLoaded', function() {
        var bodyClass = '';
        if (isIE) bodyClass = 'browser-ie';
        else if (isEdge) bodyClass = 'browser-edge';
        else if (isChrome) bodyClass = 'browser-chrome';
        else if (isFirefox) bodyClass = 'browser-firefox';
        else if (isSafari) bodyClass = 'browser-safari';

        if (bodyClass) {
            document.body.className += ' ' + bodyClass;
        }
    });

    // 增强的错误处理
    window.addEventListener('error', function(e) {
        console.error('JavaScript Error:', e.error || e.message);
        // 可选：发送错误到后端
        // fetch('/api/logs/client-error', { method: 'POST', body: JSON.stringify({error: e.message}) });
    });
})();

class PPHManagement {
    constructor() {
        // 🔧 恢复原始API配置 - 管理页面调用自己的API
        // 兼容 IE11 的 window.location.origin
        this.apiBase = (window.location.origin || (window.location.protocol + '//' + window.location.host)) + '/api';
        this.autoRefreshInterval = null;
        this.currentLogFile = null;
        this.logRefreshInterval = null;
        this.isAutoRefreshEnabled = true;
        // 审计分页状态
        this.audit = { offset: 0, limit: 100, total: 0 };

        this.init();
    }

    init() {
        this.updateCurrentTime();
        this.loadSystemInfo();
        this.loadServices();
        this.loadLogFiles();
        this.loadAuditRecords();

        // 设置定时刷新
        this.startAutoRefresh();

        // 首次检查第三方连通性
        // 首次检查第三方连通性
        try { this.checkThirdPartyConnectivity(); } catch(e) { console.warn('checkThirdPartyConnectivity init failed:', e); }

        // 每秒更新时间
        setInterval(() => this.updateCurrentTime(), 1000);
    }

    updateCurrentTime() {
        const now = new Date();
        document.getElementById('currentTime').textContent =
            now.toLocaleString('zh-CN', {
                year: 'numeric',
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
                second: '2-digit'
            });
    }

    async loadSystemInfo() {
        try {
            const response = await fetch(`${this.apiBase}/system/info`);
            const data = await response.json();

            if (data.success) {
                this.displaySystemInfo(data.system);
            } else {
                this.showError('获取系统信息失败: ' + data.error);
            }
        } catch (error) {
            this.showError('获取系统信息失败: ' + error.message);
        }
    }

    displaySystemInfo(system) {
        const memoryUsedPercent = ((system.memory.used / system.memory.total) * 100).toFixed(1);
        const uptimeHours = Math.floor(system.uptime / 3600);
        const uptimeDays = Math.floor(uptimeHours / 24);

        const mgmtUptime = typeof system.mgmtProcessUptimeMs === 'number' && system.mgmtProcessUptimeMs>0 ? this.formatUptime(system.mgmtProcessUptimeMs) : '-';
        const html = `
            <div class="mb-2">
                <strong>主机名:</strong> ${system.hostname}
            </div>
            <div class="mb-2">
                <strong>系统:</strong> ${system.platform} ${system.arch}
            </div>
            <div class="mb-2">
                <strong>系统运行时间:</strong> ${uptimeDays}天 ${uptimeHours % 24}小时
            </div>
            <div class="mb-2">
                <strong>内存使用:</strong>
                <div class="memory-bar mt-1">
                    <div class="memory-used" style="width: ${memoryUsedPercent}%"></div>
                </div>
                <small>${this.formatBytes(system.memory.used)} / ${this.formatBytes(system.memory.total)} (${memoryUsedPercent}%)</small>
            </div>
            <div class="mb-2">
                <strong>端口状态:</strong>
                <div class="mt-1">
                    <span class="badge ${system.ports.frontend ? 'bg-success' : 'bg-danger'}">
                        前端:3010 ${system.ports.frontend ? '✓' : '✗'}
                    </span>
                    <span class="badge ${system.ports.backend ? 'bg-success' : 'bg-danger'}">
                        后端:3011 ${system.ports.backend ? '✓' : '✗'}
                    </span>
                    <span class="badge ${system.ports.management ? 'bg-success' : 'bg-danger'}">
                        管理:3012 ${system.ports.management ? '✓' : '✗'}
                    </span>
                </div>
            </div>
            <div class="mb-2">
                <strong>管理端进程运行时间:</strong> ${mgmtUptime}
            </div>
        `;

        document.getElementById('systemInfo').innerHTML = html;
    }

    async loadServices() {
        try {
            const response = await fetch(`${this.apiBase}/services/status`);
            const data = await response.json();

            if (data.success) {
                this.displayServices(data.services);
            } else {
                this.showError('获取服务状态失败: ' + data.error);
            }
        } catch (error) {
            this.showError('获取服务状态失败: ' + error.message);
        }
    }

    displayServices(services) {
        const tbody = document.querySelector('#servicesTable tbody');

        if (services.length === 0) {
            tbody.innerHTML = '<tr><td colspan="8" class="text-center text-muted">没有运行的服务</td></tr>';
            return;
        }

        const html = services.map(service => {
            const statusClass = service.status === 'online' ? 'status-online' :
                               service.status === 'stopped' ? 'status-stopped' : 'status-error';
            const uptime = this.formatUptime(Date.now() - service.uptime);

            return `
                <tr>
                    <td><strong>${service.name}</strong></td>
                    <td><span class="${statusClass}"><i class="bi bi-circle-fill"></i> ${service.status}</span></td>
                    <td>${service.pid || '-'}</td>
                    <td>${uptime}</td>
                    <td>${service.restarts}</td>
                    <td>${this.formatBytes(service.memory)}</td>
                    <td>${service.cpu}%</td>
                    <td>
                        <div class="btn-group btn-group-sm">
                            <button class="btn btn-outline-success" onclick="pphMgmt.startService('${service.name}')"
                                    ${service.status === 'online' ? 'disabled' : ''}>
                                <i class="bi bi-play"></i>
                            </button>
                            <button class="btn btn-outline-warning" onclick="pphMgmt.restartService('${service.name}')"
                                    ${service.status !== 'online' ? 'disabled' : ''}>
                                <i class="bi bi-arrow-clockwise"></i>
                            </button>
                            <button class="btn btn-outline-danger" onclick="pphMgmt.stopService('${service.name}')"
                                    ${service.status !== 'online' ? 'disabled' : ''}>
                                <i class="bi bi-stop"></i>
                            </button>
                        </div>
                    </td>
                </tr>
            `;
        }).join('');

        tbody.innerHTML = html;
    }

    async loadLogFiles() {
        try {
            const response = await fetch(`${this.apiBase}/logs/list`);
            const data = await response.json();

            if (data.success) {
                this.displayLogFiles(data.logs);
            } else {
                this.showError('获取日志列表失败: ' + data.error);
            }
        } catch (error) {
            this.showError('获取日志列表失败: ' + error.message);
        }
    }

    displayLogFiles(logs) {
        const container = document.getElementById('logFilesList');

        if (logs.length === 0) {
            container.innerHTML = '<div class="text-center text-muted">没有日志文件</div>';
            return;
        }

        const html = logs.map(log => `
            <a href="#" class="list-group-item list-group-item-action"
               onclick="pphMgmt.selectLogFile('${log.name}', event); return false;">
                <div class="d-flex w-100 justify-content-between">
                    <h6 class="mb-1">${log.name}</h6>
                    <small>${this.formatBytes(log.size)}</small>
                </div>
                <small class="text-muted">${new Date(log.modified).toLocaleString('zh-CN')}</small>
            </a>
        `).join('');

        container.innerHTML = html;
    }

    async selectLogFile(filename, evt) {
        this.currentLogFile = filename;
        const e = evt || window.event || null;
        const target = e && (e.currentTarget || e.target);

        // 更新UI状态
        document.querySelectorAll('#logFilesList .list-group-item').forEach(item => {
            item.classList.remove('active');
        });
        if (target && target.closest) {
            target.closest('.list-group-item').classList.add('active');
        }

        // 启用导出按钮
        const exportBtn = document.getElementById('exportBtn');
        if (exportBtn) exportBtn.disabled = false;

        // 加载日志内容
        await this.loadLogContent(filename);

        // 开始实时刷新
        this.startLogRefresh();
    }

    async loadLogContent(filename, lines = 100) {
        try {
            const response = await fetch(`${this.apiBase}/logs/content/${filename}?lines=${lines}`);
            const data = await response.json();

            if (data.success) {
                const logContainer = document.getElementById('logContent');
                const pre = document.createElement('pre');
                pre.textContent = data.content || '';
                logContainer.innerHTML = '';
                logContainer.appendChild(pre);
                logContainer.scrollTop = logContainer.scrollHeight;
            } else {
                this.showError('加载日志内容失败: ' + data.error);
            }
        } catch (error) {
            this.showError('加载日志内容失败: ' + error.message);
        }
    }

    startAutoRefresh() {
        if (this.autoRefreshInterval) {
            clearInterval(this.autoRefreshInterval);
        }

        this.autoRefreshInterval = setInterval(() => {
            if (this.isAutoRefreshEnabled) {
                this.loadSystemInfo();
                this.loadServices();
            }
        }, 5000); // 每5秒刷新一次
    }

    startLogRefresh() {
        if (this.logRefreshInterval) {
            clearInterval(this.logRefreshInterval);
        }

        if (this.currentLogFile && this.isAutoRefreshEnabled) {
            this.logRefreshInterval = setInterval(() => {
                this.loadLogContent(this.currentLogFile, 50);
            }, 3000); // 每3秒刷新日志
        }
    }

    toggleAutoRefresh() {
        this.isAutoRefreshEnabled = !this.isAutoRefreshEnabled;
        const btn = document.getElementById('autoRefreshBtn');

        if (this.isAutoRefreshEnabled) {
            btn.innerHTML = '<i class="bi bi-pause"></i> 暂停自动刷新';
            btn.className = 'btn btn-outline-light';
            this.startAutoRefresh();
            this.startLogRefresh();
        } else {
            btn.innerHTML = '<i class="bi bi-play"></i> 开启自动刷新';
            btn.className = 'btn btn-outline-warning';
            if (this.autoRefreshInterval) clearInterval(this.autoRefreshInterval);
            if (this.logRefreshInterval) clearInterval(this.logRefreshInterval);
        }
    }

    clearLogDisplay() {
        document.getElementById('logContent').innerHTML =
            '<div class="text-center text-muted">日志显示已清空</div>';
    }

    exportCurrentLog() {
        if (this.currentLogFile) {
            window.open(`${this.apiBase}/logs/export/${this.currentLogFile}`, '_blank');
        }
    }

    // 服务操作方法
    async startService(serviceName) {
        await this.executeServiceAction('start', serviceName, `启动服务 ${serviceName}`);
    }

    async stopService(serviceName) {
        await this.executeServiceAction('stop', serviceName, `停止服务 ${serviceName}`);
    }

    async restartService(serviceName) {
        await this.executeServiceAction('restart', serviceName, `重启服务 ${serviceName}`);
    }

    async startAllServices() {
        await this.executeServiceAction('start', 'all', '启动所有服务');
    }

    async stopAllServices() {
        await this.executeServiceAction('stop', 'all', '停止所有服务');
    }

    async restartAllServices() {
        await this.executeServiceAction('restart', 'all', '重启所有服务');
    }

    async executeServiceAction(action, service, description) {
        if (!confirm(`确定要${description}吗？`)) {
            return;
        }

        this.showLoading(`正在${description}...`);

        try {
            // 前端增加超时控制，避免请求长时间挂起导致界面卡住
            const controller = new AbortController();
            const timer = setTimeout(function(){ controller.abort(); }, 15000); // 15秒超时

            // 切换到“异步队列”接口，立即返回 jobId，前端轮询状态
            const response = await fetch(`${this.apiBase}/services/queue`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action, service }),
                signal: controller.signal
            });
            clearTimeout(timer);

            const data = await response.json();

            if (data.success && data.jobId) {
                // 暂停自动刷新，轮询任务状态
                const jobId = data.jobId;
                this.isAutoRefreshEnabled = false;
                const btn = document.getElementById('autoRefreshBtn');
                if (btn) { btn.innerHTML = '<i class="bi bi-play"></i> 开启自动刷新'; btn.className = 'btn btn-outline-warning'; }

                await this.pollJob(jobId, description);
            } else {
                this.showError(`${description}提交失败: ${data.error || '未知错误'}`);
            }
        } catch (error) {
            if (error.name === 'AbortError') {
                this.showError(`${description}超时(>15秒)，后台可能仍在处理，请稍后点击“刷新状态”查看`);
            } else {
                this.showError(`${description}失败: ${error.message}`);
            }
        } finally {
            this.hideLoading();
        }

    }

    async pollJob(jobId, description){
        const start = Date.now();
        const timeoutMs = 30000; // 30秒上限
        try{
            while(Date.now() - start < timeoutMs){
                await new Promise(r=>setTimeout(r, 1000));
                const resp = await fetch(`${this.apiBase}/jobs/status/${jobId}`);
                const data = await resp.json();
                if(!data.success){
                    this.showError(`${description}失败: 无法获取任务状态`);
                    return;
                }
                const { job } = data;
                if(job.status === 'success'){
                    this.showSuccess(`${description}成功`);
                    this.isAutoRefreshEnabled = true;
                    this.startAutoRefresh();
                    this.startLogRefresh();
                    this.loadServices();
                    this.refreshAudit();
                    return;
                }
                if(job.status === 'failed'){
                    let err = '未知错误';
                    try{
                        if (job && typeof job === 'object') {
                            if (job.result && job.result.error) err = job.result.error;
                            else if (job.error) err = job.error;
                        }
                    }catch(_){/* 忽略 */}
                    this.showError(`${description}失败: ${err}`);
                    this.refreshAudit();
                    return;
                }
            }
            this.showError(`${description}超时(>30秒)，后台可能仍在处理，请稍后点击“刷新状态”查看`);
        }catch(e){
            this.showError(`${description}失败: ${e.message}`);
        }
    }

    refreshServices() {
        this.loadServices();
        this.loadSystemInfo();
        this.showSuccess('状态已刷新');
    }


    // 第三方连通性检测（完全兼容ES5语法）
    checkThirdPartyConnectivity() {
        var el = document.getElementById('thirdPartyStatus');
        if (!el) { return; }
        el.innerHTML = '<span class="badge bg-secondary">检测中...</span>';

        var self = this;
        var controller = new AbortController();
        var timer = setTimeout(function() { controller.abort(); }, 5000);

        try {
            var url = (window.location.origin || (window.location.protocol + '//' + window.location.host)) + '/api/third-party/dsp/ping';
            fetch(url, { method: 'GET', signal: controller.signal })
                .then(function(resp) {
                    clearTimeout(timer);
                    if (!resp || !resp.ok) {
                        el.innerHTML = '<span class="badge bg-danger">离线</span>';
                        return Promise.resolve({ success: false });
                    }
                    return resp.json().catch(function() { return { success: false }; });
                })
                .then(function(data) {
                    if (data && data.success) {
                        el.innerHTML = '<span class="badge bg-success">连通</span>';
                    } else {
                        el.innerHTML = '<span class="badge bg-danger">离线</span>';
                    }
                })
                .catch(function() {
                    clearTimeout(timer);
                    el.innerHTML = '<span class="badge bg-danger">离线</span>';
                });
        } catch (e) {
            clearTimeout(timer);
            el.innerHTML = '<span class="badge bg-danger">离线</span>';
        }
    }





    async loadAuditRecords() {
        try {
            var actionEl = document.getElementById('auditAction');
            var serviceEl = document.getElementById('auditService');
            var successEl = document.getElementById('auditSuccess');
            const action = encodeURIComponent(actionEl && actionEl.value ? actionEl.value : '');
            const service = encodeURIComponent(serviceEl && serviceEl.value ? serviceEl.value : '');
            const success = encodeURIComponent(successEl && successEl.value ? successEl.value : '');
            const { offset, limit } = this.audit;
            const url = `${this.apiBase}/audit/list?limit=${limit}&offset=${offset}&action=${action}&service=${service}&success=${success}`;
            const response = await fetch(url);
            const data = await response.json();
            if (!data.success) {
                document.getElementById('auditTableBody').innerHTML = '<tr><td colspan="6" class="text-center text-muted">暂无记录</td></tr>';
                document.getElementById('auditPageInfo').textContent = '';
                return;
            }
            this.audit.total = data.total || 0;
            const rows = data.items || [];
            const html = rows.map(r => `
                <tr>
                    <td>${new Date(r.ts).toLocaleString('zh-CN')}</td>
                    <td>${r.ip || '-'}</td>
                    <td>${r.action}</td>
                    <td>${r.service}</td>
                    <td>${r.success ? '<span class="text-success">成功</span>' : '<span class="text-danger">失败</span>'}</td>
                    <td>${r.error ? this.escapeHtml(String(r.error)).slice(0,120) : '-'}</td>
                </tr>`).join('');
            document.getElementById('auditTableBody').innerHTML = html || '<tr><td colspan="6" class="text-center text-muted">暂无记录</td></tr>';
            const page = Math.floor(offset/limit)+1;
            const pages = Math.max(1, Math.ceil((this.audit.total||0)/limit));
            document.getElementById('auditPageInfo').textContent = `第 ${page}/${pages} 页，共 ${this.audit.total} 条`;
        } catch (e) {
            document.getElementById('auditTableBody').innerHTML = '<tr><td colspan="6" class="text-center text-danger">加载失败</td></tr>';
        }
    }

    // 供按钮调用
    refreshAudit() { this.audit.offset = 0; this.loadAuditRecords(); }
    nextAuditPage(){ const {offset,limit,total}=this.audit; if(offset+limit<total){ this.audit.offset+=limit; this.loadAuditRecords(); } }
    prevAuditPage(){ const {offset,limit}=this.audit; if(offset-limit>=0){ this.audit.offset-=limit; this.loadAuditRecords(); } }

    // 工具方法
    formatBytes(bytes) {
        if (bytes === 0) return '0 B';
        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    formatUptime(ms) {
        const seconds = Math.floor(ms / 1000);
        const minutes = Math.floor(seconds / 60);
        const hours = Math.floor(minutes / 60);
        const days = Math.floor(hours / 24);

        if (days > 0) return `${days}天${hours % 24}时`;
        if (hours > 0) return `${hours}时${minutes % 60}分`;
        if (minutes > 0) return `${minutes}分${seconds % 60}秒`;
        return `${seconds}秒`;
    }

    escapeHtml(text){
        const map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' };
        return String(text).replace(/[&<>"']/g, m => map[m]);
    }

    showLoading(message) {
        document.getElementById('loadingMessage').textContent = message;
        new bootstrap.Modal(document.getElementById('loadingModal')).show();
    }

    hideLoading() {
        const modal = bootstrap.Modal.getInstance(document.getElementById('loadingModal'));
        if (modal) modal.hide();
    }

    showSuccess(message) {
        this.showToast(message, 'success');
    }

    showError(message) {
        this.showToast(message, 'danger');
    }

    showToast(message, type) {
        // 创建toast元素
        const toastHtml = `
            <div class="toast align-items-center text-white bg-${type} border-0" role="alert">
                <div class="d-flex">
                    <div class="toast-body">${message}</div>
                    <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
                </div>
            </div>
        `;

        // 添加到页面
        let toastContainer = document.getElementById('toastContainer');
        if (!toastContainer) {
            toastContainer = document.createElement('div');
            toastContainer.id = 'toastContainer';
            toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3';
            toastContainer.style.zIndex = '9999';
            document.body.appendChild(toastContainer);
        }

        toastContainer.insertAdjacentHTML('beforeend', toastHtml);

        // 显示toast
        const toastElement = toastContainer.lastElementChild;
        const toast = new bootstrap.Toast(toastElement, { delay: 3000 });
        toast.show();

        // 自动移除
        toastElement.addEventListener('hidden.bs.toast', () => {
            toastElement.remove();
        });
        }

        // 系统级操作（仅本机调用）
        async setupPm2Startup(){
            // Windows 环境：引导用户使用 pm2-windows-startup 手动安装
            // 兼容性检测：使用更可靠的方式检测 Windows
            var isWindows = navigator.platform && (navigator.platform.toLowerCase().indexOf('win') !== -1) ||
                           navigator.userAgent && (navigator.userAgent.toLowerCase().indexOf('windows') !== -1);
            if (isWindows) {
                this.showError('Windows 上请以管理员 PowerShell 运行: npm i -g pm2-windows-startup && pm2-startup install && pm2 save');
                return;
            }
            this.showLoading('正在设置 PM2 开机自启并保存...');
            try{
                const res = await fetch(`${this.apiBase}/system/pm2/startup-save`, { method:'POST' });
                const data = await res.json();
                if(data.success){ this.showSuccess('PM2 开机自启配置已完成'); }
                else{ this.showError('设置失败: ' + (data.error || '未知错误')); }
            }catch(e){ this.showError('设置失败: ' + e.message); }
            finally{ this.hideLoading(); }
        }

        async openFirewall(){
            // Windows 环境：引导用户使用手动命令
            // 兼容性检测：使用更可靠的方式检测 Windows
            var isWindows = navigator.platform && (navigator.platform.toLowerCase().indexOf('win') !== -1) ||
                           navigator.userAgent && (navigator.userAgent.toLowerCase().indexOf('windows') !== -1);
            if (isWindows) {
                const commands = [
                    'netsh advfirewall firewall add rule name="PPH-Frontend-3010" dir=in action=allow protocol=TCP localport=3010',
                    'netsh advfirewall firewall add rule name="PPH-Backend-3011" dir=in action=allow protocol=TCP localport=3011',
                    'netsh advfirewall firewall add rule name="PPH-Management-3012" dir=in action=allow protocol=TCP localport=3012'
                ];
                this.showError('Windows 防火墙请以管理员 CMD 执行以下命令：\\n\\n' + commands.join('\\n\\n'));
                return;
            }
            this.showLoading('正在放行防火墙端口 3010/3011/3012...');
            try{
                const res = await fetch(`${this.apiBase}/system/firewall/open`, { method:'POST' });
                const data = await res.json();
                if(data.success){ this.showSuccess('防火墙规则已添加'); }
                else{ this.showError('放行失败: ' + (data.error || '未知错误')); }
            }catch(e){ this.showError('放行失败: ' + e.message); }
            finally{ this.hideLoading(); }
        }










}

// 全局实例
const pphMgmt = new PPHManagement();

// 兼容旧版 HTML 的全局函数别名（用于 index.html 中的 onclick）
try {
  window.startAllServices = () => pphMgmt.startAllServices();
  window.restartAllServices = () => pphMgmt.restartAllServices();
  window.stopAllServices = () => pphMgmt.stopAllServices();
  window.refreshServices = () => pphMgmt.refreshServices();
  window.toggleAutoRefresh = () => pphMgmt.toggleAutoRefresh();
  window.clearLogDisplay = () => pphMgmt.clearLogDisplay();
  window.exportCurrentLog = () => pphMgmt.exportCurrentLog();
  window.refreshAudit = () => pphMgmt.refreshAudit();

  // 将系统操作暴露为全局函数，避免类体解析问题导致的 SyntaxError
  window.setupPm2Startup = () => { try{ pphMgmt.setupPm2Startup(); } catch(e){ console.error(e); } };
  window.openFirewall = () => { try{ pphMgmt.openFirewall(); } catch(e){ console.error(e); } };
} catch (e) {
  // noop
}
